﻿#region Copyright

// /*
// SilverlightInEnterprise
// SilverlightInEnterprise.SharedCode.Repository
// InteractiveCacheRepository.cs
// 
// Author: Matt Van Horn
// Created 11/17/2011 2:41 PM
// Copyright: Silverlight in the Enterprise www.slinenterprise.com
// 
// Licensed under MS-PL http://www.opensource.org/licenses/MS-PL and while you 
// may use this in anyway you see fit and owe us nothing to do so, we wouldn't mind knowing that you got value out of the work we did (so we will do more) so 
// we ask that you leave a comment on www.slinenterprise.com or on the codeplex site slinenterprise.codeplex.com
// 
// */

#endregion

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Linq.Expressions;

namespace SilverlightInEnterprise.SharedCode.Repository.Cache
{
    public abstract class InteractiveCacheRepository<TModel, TKey> : IInteractiveCacheRepository<TModel, TKey>
        where TModel : class
    {
        protected TKey LastKey { get; set; }
        private readonly ObservableCollection<TModel> items;
        private readonly ReadOnlyObservableCollection<TModel> readOnlyItems;

        public InteractiveCacheRepository(IEnumerable<TModel> items)
        {
            this.items = new ObservableCollection<TModel>(items);
            this.readOnlyItems = new ReadOnlyObservableCollection<TModel>(this.items);
        }


        public void Delete(TKey key)
        {
            var item = this.GetItemByKey(key);
            this.items.Remove(item);
            this.OnDeleted(key, item);
        }

        protected abstract void SetInsertedItemKey(TModel item);

        protected virtual void OnInsert(TModel item)
        {
        }

        protected virtual void OnUpdated(TModel updated, TModel orignal)
        {
        }

        protected virtual void OnDeleted(TKey key, TModel item)
        {
        }

        public void Insert(TModel item)
        {
            this.SetInsertedItemKey(item);
            this.items.Add(item);
            this.OnInsert(item);
        }

        public void Update(TModel item)
        {
            TKey key = this.ValueFunc.Invoke(item);
            TModel orignalItem = this.items.FirstOrDefault(i => key.Equals(this.ValueFunc.Invoke(i)));
            int index = this.items.IndexOf(orignalItem);
            this.items[index] = item;
            this.OnUpdated(item, orignalItem);
        }

        public ReadOnlyObservableCollection<TModel> ObservableItems
        {
            get { return this.readOnlyItems; }
        }

        public static IInteractiveCacheRepository<TModel, TKey> Cache { get; protected set; }

        public IEnumerable<TModel> Items
        {
            get { return this.items; }
        }

        public Func<TModel, string> DisplayValueFunc { get; protected set; }

        public Func<TModel, TKey> ValueFunc { get; protected set; }

        public TReturn GetCachedPropertyFromKey<TReturn>(TKey key, Expression<Func<TModel, TReturn>> expression)
        {
            TReturn cachedPropertyValue = default(TReturn);
            if (key == null) return cachedPropertyValue;
            var item = this.Items.FirstOrDefault(i => key.Equals(ValueFunc.Invoke(i)));
            if (item != null)
            {
                cachedPropertyValue = expression.Compile().Invoke(item);
            }
            return cachedPropertyValue;
        }

        public TModel GetItemByKey(TKey key)
        {
            return this.Items.FirstOrDefault(i => key.Equals(this.ValueFunc.Invoke(i)));
        }
    }
}